<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script>
    // 仅对同步脚本有效
    window.addEventListener('error', function(e) {
      console.log(e)
      if(e instanceof ErrorEvent) return // 如果是自定义错误 结束(自定义错误继承自...)
      let domainList = [ // 域名重试列表
        'wsj.com',
        'wcx.dog',
        'lk.dog',
        'localhost:8888'
      ]
      let url = new URL(e.target.src) // 错误源关联的地址
      let index = domainList.findIndex((domin) => domin === url.host) // 当前域名
      if(index === domainList.length - 1)  return // 如果当前域名是列表最后一个，那么结束
      index = index + 1 // 下一个重试的索引
      // 保证在script加载解析和执行前优先处理，TODO:保证执行顺序
      // 文档解析完成后执行write会重新刷行整个文档，但是在解析没完成前执行会在中间插入脚本，当前脚本是同步的（无defer/async标记）
      document.write(`\<script src="${url.protocol}//${domainList[index]}${url.pathname}"\>\<\/script\>`)
      
      // 替换链接重新加载整个文档，为了保证defer的加载顺序（无用...）
      let newScript = document.createElement('script');
      newScript.src = `${url.protocol}//${domainList[index]}${url.pathname}`;
      newScript.defer = true; // 使用 defer 确保脚本按照顺序加载
      e.target.parentNode.insertBefore(newScript, e.target)
      e.target.remove()
      document.write(document.documentElement.outerHTML)
      
      // 下面的处理方式不会阻塞文档往下解析，所以会很早就触发DCL导致script1和script3执行了
      /*
      let newScript = document.createElement('script');
      newScript.src = `${url.protocol}//${domainList[index]}${url.pathname}`;
      newScript.defer = true; // 使用 defer 确保脚本按照顺序加载
      e.target.parentNode.insertBefore(newScript, e.target)
      */
      return false
    }, true) // 捕获阶段拦截，不然错误不会冒泡捕获不到
  </script>
  <!-- <script src="./script1.js" defer></script> -->
  <script src="./script1.js"></script>
  <script src="./script2.js"></script>
  <script src="./script3.js"></script>
  <script>
    // throw new Error('123123')
  </script>
</head>
<body>
  <div>hello</div>
</body>
</html>